package ufw.tree;

import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import ufw.collection.MapTree;
import ufw.node2List.Node2List;
import ufw.prototype.TreeSearch;
import ufw.prototype.TreeSearchBaseCallback;

@SuppressWarnings("serial")
public class ProtoTreeSearchTest {
	private static Logger logger = LoggerFactory.getLogger(MapTreeTest.class);
		
		private static Map<String, String> getMap(final String id) {
			return new HashMap<String, String>() {{ put("key", "key-" + id); put("value", "value-" + id); }};
		}
		
		private static DefaultMutableTreeNode getTree(final DefaultMutableTreeNode parentNode, final String seq) {
			return new DefaultMutableTreeNode() {{ setUserObject(getMap(seq)); parentNode.add(this); }};
		}
		
		// 테스트 소스 생성 - 시작
		private DefaultMutableTreeNode getTreeNodeSource() {
			DefaultMutableTreeNode node = null;
			DefaultMutableTreeNode child = null;
			DefaultMutableTreeNode son = null;
			
			node = new DefaultMutableTreeNode();
			node.setUserObject(getMap("0"));
			
			for (int i = 1; i <= 2; i++) {
				child =	getTree(node, Integer.toString(i));
				
				for (int j = 1; j <= 2; j++) {
					son =	getTree(child, Integer.toString(i) + "-" + Integer.toString(j));
					
					for (int k = 1; k <= 2; k++) {
						getTree(son, Integer.toString(i) + "-" + Integer.toString(j) + "-" + Integer.toString(k));
					}
				}
			}
			
			return node;
		}
		// 테스트 소스 생성 - 종료
		
		private static void logTree(final DefaultMutableTreeNode tree) {
			final Enumeration<TreeNode> allnode = tree.depthFirstEnumeration();
			
			while (allnode.hasMoreElements()) {
				final TreeNode eachnode = allnode.nextElement();
				logger.debug("node:" + eachnode.toString() + ",parent:" + (eachnode.getParent() == null ? "no parent" : eachnode.getParent().toString()));
			}
		}
		
	@Test
	public void testTreeNodeNavigate() {
		DefaultMutableTreeNode source = getTreeNodeSource();
		logTree(source);
		
		TreeSearchBaseCallback.MutableTreeNodeSource sourceCallback = new TreeSearchBaseCallback.MutableTreeNodeSource(source);
		TreeSearchBaseCallback.MapTarget callback = new TreeSearchBaseCallback.MapTarget(new HashMap<String, Object>());
		
		TreeSearch.navigate(sourceCallback, callback);
		
		logger.debug(callback.getData().toString());
	}

		private static MapTree getTree(final MapTree parent, final String seq) {
			return parent.add(getMap(seq));
		}		
		
		// 테스트 소스 생성 - 시작
		public static MapTree getMapTreeSource() {
			MapTree node = null;
			MapTree child =	null;
			MapTree son = null;
			
			node =	new MapTree(getMap("0"));
			
			for (int i = 1; i <= 2; i++) {
				child =	getTree(node, Integer.toString(i));
				
				for (int j = 1; j <= 2; j++) {
					son =	getTree(child, Integer.toString(i) + "-" + Integer.toString(j));
					
					for (int k = 1; k <= 2; k++) {
						getTree(son, Integer.toString(i) + "-" + Integer.toString(j) + "-" + Integer.toString(k));
					}
				}
			}
			
			return node;
		}
		// 테스트 소스 생성 - 종료
	
	@Test
	public void testMapTreeNavigate() {
		MapTree source = getMapTreeSource();
		
		TreeSearchBaseCallback.MapTreeSource sourceCallback = new TreeSearchBaseCallback.MapTreeSource(source);
		TreeSearchBaseCallback.MapTarget callback = new TreeSearchBaseCallback.MapTarget(new HashMap<String, Object>());
		
		TreeSearch.navigate(sourceCallback, callback);
		
		logger.debug(callback.getData().toString());
	}
	
		public static Node getXmlSource() {
			final InputStream stream = Node2List.class.getResourceAsStream("/tree-sample.xml");
			
			DocumentBuilder builder;
			Document doc = null;
			
			try {
				builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
				doc = builder.parse(stream);
			} catch (ParserConfigurationException e) {
				e.printStackTrace();
			} catch (SAXException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}

			logger.debug(doc.getChildNodes().toString());
			logger.debug(doc.getDocumentElement().toString());
			
			Node root = doc.getDocumentElement();
			
			logger.debug(root.getNodeName() + "," + StringUtils.trimWhitespace(root.getNodeValue()));
			
			NodeList nodeList = root.getChildNodes();
			for (int i = 0; i < nodeList.getLength(); i++) {
				Node node = nodeList.item(i);
				logger.debug(i + ":" + node.getNodeName() + "," + StringUtils.trimWhitespace(node.getNodeValue()));
				
				NodeList nodeList1 = node.getChildNodes();
				for (int j = 0; j < nodeList1.getLength(); j++) {
					Node node1 = nodeList1.item(j);
					logger.debug(i + "," + j + ":" + node1.getNodeName() + "," + StringUtils.trimWhitespace(node1.getNodeValue()));
					
					NodeList nodeList2 = node1.getChildNodes();
					for (int k = 0; k < nodeList2.getLength(); k++) {
						Node node2 = nodeList2.item(k);
						logger.debug(i + "," + j + "," + k + ":" + node2.getNodeName() + "," + StringUtils.trimWhitespace(node2.getNodeValue()));
					}
				}
			}
			
			return doc;
		}
		
	@Test
	public void testXmlNavigate() {
		Node source = getXmlSource();
		
//		TreeSearchBaseCallback.XmlSource sourceCallback = new TreeSearchBaseCallback.XmlSource(source);
//		TreeSearchBaseCallback.MapTarget callback = new TreeSearchBaseCallback.MapTarget(new HashMap<String, Object>());
//		
//		TreeSearch.navigate(sourceCallback, callback);
//		
//		logger.debug(callback.getData().toString());
	}
		
}
